home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / GRAPHICS.SWG / 0087_Delux Paint II LBM decode.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-25  |  12KB  |  410 lines

  1. {
  2. Here a program to display files from deLux Paint II (*.LBM files)
  3. drawings. It uses a PD BGI driver for 320x200x256 color mode. Other
  4. drivers can also be used. Otherwise look in the SWAG lib for routines to
  5. enter this graphics mode and set a pixel in a certain color.
  6.  
  7. Code isn't optimal and can be made much faster but works. It doesn't
  8. display some brushes because of some undocumented sections in the LBM
  9. file. If the defines are made active the file is decoded and dumped
  10. textual to the screen. After the program a part of a small PD text file
  11. I found and used as base for this program. It contained some bugs but
  12. one evening works does a lot.
  13.  
  14. Btw. Does anybody know how to distinguish deLux Paint II and deLux Paint
  15. II Enhanced files?
  16. }
  17.  
  18. {---------------------------------------------------------}
  19. { Written by : Ir. G.W. van der Vegt                      }
  20. { Purpose    : a Delux Paint II LBM file displayer/decoder}
  21. {              displays 16 and 256 color bitmaps but no   }
  22. {              brushes and Delux Paint IIe files yet      }
  23. {                                                         }
  24. {              Displays at the moment only                }
  25. {              320x200 or smaller pictures.               }
  26. {                                                         }
  27. {              Uses a PD SVGA driver to access MCGA mode. }
  28. {              Substitute your own if you havn't got it.  }
  29. {                                                         }
  30. { File format info by Bob Montgomery 9-21-90, although    }
  31. { it wasn't very accurate (he forgot Motorola swaps       }
  32. { lo & hi byes of words) and didn't cover the             }
  33. { DPPV, CRNG & GRAB sections.                             }
  34. {                                                         }
  35. { Use the verbose (and rle) defines to get a dump of the  }
  36. { lbm file.                                               }
  37. {---------------------------------------------------------}
  38.  
  39. PROGRAM lbm(INPUT,OUTPUT);
  40.  
  41. USES
  42.   crt,
  43.   dos,
  44.   graph;
  45.   routines;
  46.  
  47. { DEFINE verbose}
  48. { DEFINE rle    }
  49. {$I SVGA256.INC}
  50.  
  51. TYPE
  52.   rgb  = (r,g,b);
  53.   dp2l = ARRAY[0..3] OF BYTE; {read left to right}
  54.   dp2m = ARRAY[1..4] OF CHAR;
  55.   dp2t = ARRAY[rgb] OF BYTE;
  56.   dp2h = RECORD
  57.            msg1         : dp2m; { "FORM" }
  58.            flen         : dp2l;                 { File length - 8 }
  59.            msg2,                { "ILBM" }
  60.            msg3         : dp2m; { "BMHD" }
  61.            hlen         : dp2l;                 { Length of header }
  62.            width,
  63.            Length,
  64.            xoff,
  65.            yoff         : WORD;
  66.            planes,
  67.            masking,
  68.            compression,
  69.            pad          : BYTE;
  70.            tansparent   : INTEGER;
  71.            x_aspect,
  72.            y_aspect     : BYTE;
  73.            screenwidth,
  74.            screenheight : WORD;
  75.          END;
  76.  
  77. CONST
  78.   max  = 1023;
  79.  
  80. VAR
  81.    f   : FILE;
  82.    dp2 : dp2h;
  83.    msg : dp2m;
  84.    len : dp2l;
  85.    col : dp2t;
  86.  
  87.    i,
  88.    j,
  89.    k,
  90.    y   : INTEGER;
  91.    c   : BYTE;
  92.    bl,
  93.    h,
  94.    l   : LONGINT;
  95.    w   : WORD;
  96.    grmode,
  97.    grdriver : INTEGER;
  98.    lin      : ARRAY[0..max] OF BYTE;
  99.  
  100. CONST
  101.   form  : dp2m = ('F','O','R','M');
  102.   ilbm  : dp2m = ('I','L','B','M');
  103.   bmhd  : dp2m = ('B','M','H','D');
  104.   cmap  : dp2m = ('C','M','A','P');
  105.   body  : dp2m = ('B','O','D','Y');
  106.  
  107. {$F+}
  108. FUNCTION Detectvga256 : INTEGER;
  109.  
  110. BEGIN
  111.   Detectvga256 := svga320x200x256;
  112. END;
  113. {$F-}
  114. FUNCTION Len2long(a : dp2l) : LONGINT;
  115.  
  116. BEGIN
  117.   Len2long:=(((a[0]*256+a[1])*256+a[2])*256+a[3]);
  118. END;
  119.  
  120. FUNCTION Msg2str(a : dp2m) : STRING;
  121.  
  122. BEGIN
  123.   Msg2str:=a[1]+a[2]+a[3]+a[4];
  124. END;
  125.  
  126. FUNCTION Readnext : BYTE;
  127.  
  128. VAR
  129.  w : WORD;
  130.  c : BYTE;
  131.  
  132. BEGIN
  133.   Blockread(f,c,1,w);
  134.   IF (w<>1)
  135.     THEN
  136.       BEGIN
  137.         Closegraph;
  138.         Writeln('Unexpected EOF encountered');
  139.         Halt(3);
  140.       END
  141.     ELSE Readnext:=c;
  142. END;
  143.  
  144. CONST
  145.   cnt : BYTE    = 0;
  146.   rle : BOOLEAN = false;
  147.   dat : BYTE    = 0;
  148.   vir : LONGINT = 0;
  149.   rel : LONGINT = 0;
  150.  
  151. FUNCTION Getnext : BYTE;
  152.  
  153. VAR
  154.   c : BYTE;
  155.   w : WORD;
  156.  
  157. BEGIN
  158. (*
  159. get a code BYTE from the data stream.
  160. IF the msb is 1, the 'count' is (1 - code), max = 127. get the next
  161.    BYTE from the data stream, AND REPEAT it 'count' times.
  162. IF the msb is 0, the 'count' is (1 + code), max = 128. get the next
  163.    'count' bytes from the data stream.
  164. *)
  165.   IF (dp2.compression=0)
  166.     THEN Getnext:=Readnext
  167.     ELSE
  168.       IF (cnt=0)
  169.         THEN
  170.           BEGIN
  171.             c:=Readnext;
  172.             rle:=(c>127);
  173.             IF rle
  174.               THEN
  175.                 BEGIN
  176.                   cnt    :=SHORTINT(1-c);
  177.                   dat    :=Readnext;
  178.                   Getnext:=dat;
  179. {$IFDEF rle}
  180.   Delay(500);
  181.   Writeln;
  182.   Write('RLE : ',byte2hex(c),' = ',cnt:3,'x',byte2hex(dat));
  183. {$ENDIF}
  184.                 END
  185.               ELSE
  186.                 BEGIN
  187.                   cnt    :=1+c;
  188.                   dat    :=Readnext;
  189.                   Getnext:=dat;
  190. {$IFDEF rle}
  191.   Delay(500);
  192.   Writeln;
  193.   Write('UNC : ',byte2hex(c),' : ',byte2hex(dat));
  194. {$ENDIF}
  195.                 END;
  196.           END
  197.         ELSE
  198.           BEGIN
  199.             IF NOT(rle)
  200.               THEN dat:=Readnext;
  201.             Getnext:=dat;
  202. {$IFDEF rle}
  203.   IF NOT(rle) THEN Write(' ',byte2hex(dat));
  204. {$ENDIF}
  205.           END;
  206.  
  207.   Dec(cnt);
  208.   rel:=Filepos(f)-h;
  209.   Inc(vir);
  210. END;
  211.  
  212. BEGIN
  213.   Assign(f,Paramstr(1)+'.lbm');
  214.   Reset(f,1);
  215.  
  216.   Blockread(f,dp2,Sizeof(dp2));
  217.  
  218.   WITH dp2 DO
  219.     BEGIN
  220. {$IFDEF verbose}
  221.       FOR i:=1 TO Sizeof(msg1) DO Write(msg1[i]); Writeln;
  222.       FOR i:=1 TO Sizeof(msg2) DO Write(msg2[i]); Writeln;
  223. {$ENDIF}
  224.       IF (msg1<>form) OR (msg2<>ilbm) OR (msg3<>bmhd)
  225.         THEN
  226.           BEGIN
  227.             Writeln('No DeLux Paint LBM file.');
  228.             Halt(1);
  229.           END;
  230.  
  231. {$IFNDEF verbose}
  232.       grdriver:=Installuserdriver('SVGA256',@detectvga256);
  233.       grmode  :=svga320x200x256;
  234.       grdriver:=detect;
  235.       Initgraph(grdriver,grmode,'');
  236. {$ENDIF}
  237.  
  238.     {----Low & high words/bytes are swapped (Motorola 680x0 convention)}
  239. {$IFDEF verbose}
  240.       Writeln('filelength : ',Len2long(flen));
  241.       Writeln('headlength : ',Len2long(hlen));
  242. {$ENDIF}
  243.  
  244.     {----Low & high bytes are swapped (Motorola 680x0 convention)}
  245.       width       :=Swap(width);
  246.       Length      :=Swap(Length);
  247.       xoff        :=Swap(xoff);
  248.       yoff        :=Swap(yoff);
  249.       screenwidth :=Swap(screenwidth);
  250.       screenheight:=Swap(screenheight);
  251.  
  252. {$IFDEF verbose}
  253.       Writeln('W .L  : ',width      ,'x',Length);
  254.       Writeln('Xo.Yo : ',xoff       ,'x',yoff  );
  255.       Writeln('Xa.Ya : ',x_aspect   ,'x',y_aspect);
  256.       Writeln('W. H  : ',screenwidth,'x',screenheight);
  257.       Writeln('Planes: ',planes);
  258.       Writeln('Pad   : ',pad);
  259. {$ENDIF}
  260.  
  261.       Blockread(f,msg,Sizeof(msg));
  262.       Blockread(f,len,Sizeof(len));
  263.  
  264. {$IFDEF verbose}
  265.       Writeln(Msg2str(msg));
  266.       Delay(1000);
  267. {$ENDIF}
  268.  
  269.       IF (msg=cmap)
  270.         THEN
  271.           BEGIN
  272.             l:=Len2long(len);
  273. {$IFDEF verbose}
  274.             Writeln('CMAPlen : ',l);
  275. {$ENDIF}
  276.             FOR i:=1 TO l DIV 3 DO
  277.               BEGIN
  278.                 Blockread(f,col,Sizeof(col));
  279. {$IFDEF verbose}
  280.                 Delay(100);
  281.                 Writeln(i-1:4,col[r]:4,col[g]:4,col[b]:4);
  282. {$ELSE}
  283.                 Setrgbpalette(i-1,col[r] DIV 4,col[g] DIV 4,col[b] DIV 4);
  284. {$ENDIF}
  285.               END;
  286.             Blockread(f,msg,Sizeof(msg));
  287.           END;
  288.  
  289. {----dump unkown sections dppv
  290.      the 4 bytes Length is mostly 104 bytes
  291. }
  292. {----dump unkown sections grab
  293.      the 4 bytes Length is 4, section found IN a brush only,
  294. }
  295. {----dump 4 unkown sections crng :
  296.      seems each TO consist OF two entries WITH :
  297.               00 00 0a aa,00 00 01 0e
  298.               00 00 0a aa,00 00 00 00
  299.               00 00 0a aa,00 00 00 00
  300.               00 00 0a aa,00 00 00 00
  301.      brushes contain different values.
  302. }
  303.       WHILE (msg<>body) DO
  304.         BEGIN
  305.           Blockread(f,len,Sizeof(len));
  306.           l:=Len2long(len);
  307.           Writeln(Msg2str(msg)+' : ',l);
  308.           FOR h:=1 TO l DO
  309.             BEGIN
  310.               Blockread(f,c,1);
  311.               Write(' ',byte2hex(c));
  312.             END;
  313.           Blockread(f,msg,Sizeof(msg));
  314.           Writeln;
  315.         END;
  316.  
  317.       IF (msg=body)
  318.         THEN
  319.           BEGIN
  320. {$IFDEF verbose}
  321.             Writeln(Msg2str(msg));
  322. {$ENDIF}
  323.             Blockread(f,len,Sizeof(len));
  324.             l:=Len2long(len);
  325.             h :=Filepos(f);
  326. {$IFDEF verbose}
  327.             Writeln('BODYlen : ',l);
  328. {$ENDIF}
  329.             IF compression=0
  330.               THEN bl:=l DIV Length DIV planes
  331.               ELSE bl:=width DIV 8;
  332. {$IFDEF verbose}
  333.             Writeln('Bytew   : ',bl);
  334. {$ENDIF}
  335.             FOR y:=1 TO Length DO
  336.               BEGIN
  337.                 FOR i:=0 TO max DO lin[i]:=0;
  338. {$R-}
  339.                 FOR j:=0 TO planes-1 DO
  340.                   FOR i:=0 TO bl-1 DO
  341.                     BEGIN
  342.                       c:=Getnext;
  343.                       FOR k:=0 TO 7 DO
  344.                         IF (c AND (128 SHR k))>0
  345.                           THEN lin[(i*8)+k]:=lin[(i*8)+k] OR 1 SHL j;
  346.                     END;
  347. {$R+}
  348. {$IFNDEF verbose}
  349.                 FOR i:=1 TO width DO
  350.                   Putpixel(i,y,lin[i])
  351. {$ENDIF}
  352.               END;
  353.  
  354.           END;
  355.  
  356. {$IFNDEF verbose}
  357.       WHILE NOT Keypressed DO;
  358.       Closegraph;
  359. {$ELSE}
  360.       Writeln('image  ',LONGINT(width)*Length*planes DIV 8);
  361.       Writeln('bodys  ',h);
  362.       Writeln('files  ',Filesize(f));
  363.       Writeln('filep  ',Filepos(f));
  364.       Writeln('heads  ',Sizeof(dp2h));
  365.       Writeln('virtu  ',vir);
  366. {$ENDIF}
  367.       Close(f);
  368.     END;
  369.  
  370. END.
  371.  
  372. (*
  373. deluxe paint ii lbm & iff files
  374.  
  375. the deluxe paint lbm (AND iff) FILE header (40 bytes) has the following
  376. content:
  377.      struct dp2
  378.      {   CHAR msg1[4];               "form"
  379.          BYTE a3, a2, a1, a0;        FILE Length - 8  (Read left TO right)
  380.          CHAR msg2[8];               "ilbmbmhd"
  381.          BYTE b3, b2, b1, b0;        Length OF header (Read left TO right)
  382.          Int  width, Length, xoff, yoff;
  383.          BYTE planes, masking, compression, pad;
  384.          Int  tansparent;
  385.          BYTE x_aspect, y_aspect;
  386.          Int  screenwidth, screenheight;
  387.      } ;
  388.    there may be a color map following a STRING "cmap" IN the FILE. after cmap
  389.         is the Length OF the color map (4 bytes, Read left TO right). the color
  390.         map is BYTE triples (r, g, b) FOR each colors. the number OF colors is
  391.         1 shifted left by planes (1 << planes).
  392.    the actual picture data follows a STRING "body" AND Length OF the picture
  393.         data (4 bytes Read left TO right). the picture data is organized on a
  394.         color plane basis FOR dp2, AND on a pixel basis FOR dp2e (enhanced).
  395.         thus, FOR dp2:
  396.             there are (width / 8) bytes per row.
  397.             the data stream FOR each row consists OF all the bytes FOR plane 0,
  398.                 followed by all the bytes FOR plane 1, etc.
  399.         AND FOR dp2e:
  400.             there are (width) bytes/row, where each BYTE is a pixel color.
  401.    IF the data is uncomperessed (compression flag = 0), the data stream bytes
  402.         are fed TO the OUTPUT unmodified. IF it is compressed, it is run Length
  403.         encoded as follows:
  404.             get a code BYTE from the data stream.
  405.             IF the msb is 1, the 'count' is (1 - code), max = 127. get the next
  406.                 BYTE from the data stream, AND REPEAT it 'count' times.
  407.             IF the msb is 0, the 'count' is (1 + code), max = 128. get the next
  408.                 'count' bytes from the data stream.
  409. *)
  410.